home *** CD-ROM | disk | FTP | other *** search
-
- /*
- ** DFIX (C)1985 Howard Rumsey Jr.
- **
- ** DFIX disk fix utility. Reads the whole DOS partion on a disk (floppy,
- ** hard disk, ramdisk) and, if directed, marks bad clusters in the FAT(s).
- **
- ** Usage:
- ** dfix [d:]
- **
- ** d: is an optional device specifier. If not specified DFIX will
- ** use the default device.
- **
- ** If DFIX finds a bad cluster already allocated to a file this will
- ** be reported and no further action taken. If DFIX finds an unallocated
- ** cluster it marks it's local copy of the FAT. At the end of the testing
- ** the user is asked if he wishes to permanently mark the cluster as BAD.
- **
- */
-
- /*
- **
- ** DFIX is a substitute for the disktest program included with Version 3
- ** of The Norton Utilities (tm?). The Norton package contains many other
- ** useful tools. I wrote this program and am placing it in public domain
- ** because of it's (sometimes) critical value.
- **
- ** This program may be freely copied and used for any non-commercial
- ** purpose.
- **
- ** Howard Rumsey
- ** Caltech
- ** Pasadena, CA 91125
- **
- ** CompuServe [72426,3722]
- ** March 1,1985
- **
- */
-
- #include <stdio.h>
-
- #define TRUE 1
- #define FALSE 0
-
- #define DOS12 4086 /* FAT 12 or 16 bit MAGIC NUMBER */
- #define BADMARK 0xfff7 /* FAT entry for BAD cluster */
-
- char *malloc();
-
- main(ac,av) char *av[]; {
- int dev;
-
- printf("DFIX (C) 1985 Howard Rumsey Jr.\n\n");
- if((dosVersion() & 0xff) < 2) errexit("Must have DOS 2.0 or higher.\n");
- if(ac == 1) {
- show_usage();
- dev = defaultdev(); }
- else {
- if(av[1][1] != ':' || !isalpha(av[1][0])) { show_usage(); exit(1); }
- dev = toupper(av[1][0])-'A'; }
- doOpen(dev);
- doDisk(dev);
- return 0; }
-
- show_usage() {
- fprintf(stderr, "DFIX will test the whole DOS partition.\n");
- fprintf(stderr, "If you wish, it will mark bad sectors in the FAT.\n");
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, " dfix [d:]\n");
- fprintf(stderr, "where d: is a device specifier.\n"); }
-
- errexit(str) char *str; {
- fputs(str, stderr);
- exit(-1); }
-
- char *plural(n) int n; {
- return n>1 ? (char *)&"s" : (char *)&""; }
-
- typedef unsigned int uint;
-
- #define BSIZE (14+2*8) /* Should be the size of the following structure */
- struct bootsec { /* BOOT sector structure */
- char jump[3]; /* jump around this stuff */
- char oem[8]; /* OEM name, version */
- uint bytpsec; /* bytes per sector */
- char secpclu; /* sectors per cluster */
- uint fatsec; /* no. reserved sectors = FAT start */
- char nfats; /* number of FATs */
- uint ndir; /* number of ROOT directory entries */
- uint totsec; /* number of sectors in this partition */
- char meddes; /* media descriptor byte */
- uint fatcnt; /* number of sectors in a single FAT */
- uint secptrk; /* sectors per track */
- uint nheads; /* number of heads this device */
- uint hidsec; /* number of hidden sectors */
- } *boot;
-
- int fat12; /* TRUE if 12 bit FAT entries */
- int rdsize; /* ROOT directory size in sectors */
- char *fattab; /* pointer to local copy of FAT */
- char *clubuf; /* points to cluster input buffer */
-
- extern struct { /* communicate area for device allocation data */
- int d; /* device number A=0,... */
- char mb; /* media byte */
- char spc; /* sectors per cluster */
- uint nc; /* number clusters */
- uint ss; /* sector size */
- } _alloc_tab;
-
- doOpen(dev) int dev; {
- /* Check the size of bootsec to avoid a mismatch between
- "C" and DOS data allocation */
- if(sizeof(struct bootsec) != BSIZE) errexit("BOOT sector data problem. Sorry!\n");
-
- /* Gather and print the device parameters */
-
- _alloc_tab.d = dev;
- devAlloc(); /* build the device allocation table */
- boot = (struct bootsec *) malloc(_alloc_tab.ss);
- if(boot == NULL) errexit("Can't allocate BOOT buffer\n");
- if(rdDevice(dev, 0, 1, boot) != 0) errexit("Can't read BOOT sector\n");
- /* test for compatibility of BOOT sector and _alloc_tab */
- if(_alloc_tab.mb != boot->meddes ||
- _alloc_tab.spc != boot->secpclu ||
- _alloc_tab.ss != boot->bytpsec )
- errexit("BOOT sector information error. Possibly non-DOS 2+ media.\n");
-
- /* do we have 12 bit FAT entries? */
- fat12 = (_alloc_tab.nc < DOS12);
- /* compute ROOT directory size */
- rdsize = (int) ((boot->ndir * 32L)/boot->bytpsec);
-
- /* print the device information */
- printf("\nInformation for Device %c:\n",'A'+dev);
- printf(" OEM name: %8s\n",boot->oem);
- printf(" There are %d bytes per sector.\n",boot->bytpsec);
- if(boot->secpclu == 1)
- printf(" There is one sector per cluster.\n");
- else
- printf(" There are %d sectors per cluster.\n",boot->secpclu);
- printf(" There are %d clusters numbered from 2.\n", _alloc_tab.nc);
- if(boot->nfats == 1)
- printf(" There is one FAT, %d sector%s long.\n", boot->fatcnt, plural(boot->fatcnt));
- else
- printf(" There are %d FATs, each %d sector%s long.\n", boot->nfats, boot->fatcnt, plural(boot->fatcnt));
- printf(" The ROOT directory can hold %d entries and is %d sectors long.\n", boot->ndir, rdsize);
- }
-
-
- doDisk(dev) int dev; { /* read the FATs, ROOT-dir, and clusters */
- int lsec; /* logical sector number */
- int jf, kf;
- int nbad, newbad, nbadf; /* counters for bad clusters */
- char yesno[80]; /* answer 'update' question */
-
- /* get space for one FAT and one cluster */
- fattab = malloc(boot->fatcnt * boot->bytpsec);
- if(fattab == NULL)
- errexit("Unable to allocate memory for a FAT.\n");
- clubuf = malloc(boot->bytpsec * boot->secpclu);
- if(clubuf == NULL)
- errexit("Unable to allocate memory for reading clusters.\n");
-
- printf("Reading the first FAT.\n");
- if(rdDevice(dev, boot->fatsec, boot->fatcnt, fattab) != 0)
- errexit("Can't read first FAT. Device unusable.\n");
-
- /* read the rest, one sector at a time */
- lsec = boot->fatsec + boot->fatcnt;
- for(jf=1; jf<boot->nfats; jf++) {
- printf("Reading the next FAT.\n");
- for(kf=0; kf<boot->fatcnt; kf++) {
- if(rdDevice(dev, lsec++, 1, clubuf) != 0)
- errexit("Error reading second (or later) FAT.\n");
- /* should compair FATs */ } }
-
- printf("Reading the ROOT directory.\n");
- for(jf=0; jf<rdsize; jf++)
- if(rdDevice(dev, lsec++, 1, clubuf) != 0)
- errexit("Error reading the ROOT directory. Device unusable.\n");
-
- nbad = newbad = nbadf = 0;
- printf("Checking the clusters now.\n");
- printf("Cluster ");
- for(jf=2; jf<_alloc_tab.nc+2; jf++) {
- printf("\b\b\b\b\b%5d",jf);
- if(rdDevice(dev, lsec, boot->secpclu, clubuf) != 0) {
- nbad++;
- printf("\007 is bad. ");
- switch(fatstat(jf)) {
-
- case 0:
- newbad++;
- printf("Unallocated.\n");
- pokefat(jf,BADMARK);
- break;
-
- case BADMARK:
- printf("Already marked as bad.\n");
- break;
-
- default:
- nbadf++;
- printf("Included in some file. Not marked.\n");
- break; }
- printf("Cluster "); }
- lsec += boot->secpclu; }
- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
- if(nbad == 0) {
- printf("No bad clusters were found.\n");
- return; }
- printf("The number of bad clusters found was %d.\n",nbad);
- if(nbadf != 0) {
- if(nbad == 1) printf("Some file has a bad cluster.\n");
- else printf("One or more files have bad clusters.");
- printf("The DOS command:\n copy *.* nul\n");
- printf("will check all the files in the default directory.\n");
- printf("Use the DOS 'RECOVER' utility to repair bad files.\n");
- printf("Then erase the bad files and run DFIX again.\n"); }
- if(newbad == 0) {
- printf("No %s bad clusters were found.", nbadf ? "repairable" : "new");
- return; }
- printf("The number of repairable bad clusters is %d.\n", newbad);
- printf("Do you wish to update the FAT? (y/n) ");
- gets(yesno);
- if(toupper(*yesno) == 'Y') {
- for(jf=0, lsec=boot->fatsec; jf<boot->nfats; jf++, lsec += boot->fatcnt)
- if(wrDevice(dev, lsec, boot->fatcnt, fattab) != 0)
- errexit("Can't write new FAT. Device maybe unusable\n");
- printf("FAT updated.\n"); }
- else printf("FAT not updated.\n");
- }
-
- fatstat(c) unsigned c; {
- int *jj;
- if(fat12) {
- jj = (int *) (fattab+((c+c+c) >> 4));
- if(c&1) return((*jj >> 4) & 0xfff);
- return *jj & 0xfff; }
- return ((int *) fattab)[c];
- }
-
- pokefat(c,bm) unsigned c, bm; {
- int *jj;
- if(fat12) {
- jj = (int *) (fattab+((c+c+c) >> 4));
- if(c&1) {
- *jj = (*jj & 0xf) | (bm<<4);
- return; }
- *jj = (*jj & 0xf000) | (bm & 0xfff);
- return; }
- ((int *) fattab)[c] = (int) bm;
- }
-